import { deepClone, generatePermissionTree, generateTreeData, currentOrigin } from '@engineer/utils'
import { getToken, setToken, removeToken } from '@utils/auth'
import filterWhiteRouter from '@utils/filter-white-router'
import { apiLogin, apiAccountTokenLogin, apiGetUserInfo, apiGetUserPermission } from '@api/user'
import { apiGetOperableRoleList } from '@api/role'

/**
 * 遍历后端返回的权限列表数据，生成按钮级的权限列表
 * @param {array} data 后端返回的用户权限列表
 * @returns {array} 按钮权限列表
 */
const generateRoles = data => {
  const res = []
  data.forEach(item => {
    const { type, menuAlias } = item
    if (type === 3) {
      res.push(menuAlias)
    }
  })
  return res
}

/**
 * 转化树形结构的角色列表为扁平结构
 * @param {any[]} list tree list
 * @returns {any[]} list
 */
const transformRoleList = list => {
  const res = []
  list.forEach((item = {}) => {
    const { roleid, roleName, parentRoleid, child = [] } = item
    res.push({
      roleid,
      roleName,
      parentRoleid
    })
    if (child && child.length > 0) {
      const r = transformRoleList(child)
      res.push(...r)
    }
  })
  return res
}

/**
 * 格式化树形角色列表字段key
 * @param {any[]} list tree list
 * @returns {any[]} tree list
 */
const formatTreeRoleList = list => {
  const res = []
  list.forEach(item => {
    const { roleid, roleName, parentRoleid, child = [] } = item
    const temp = {
      roleId: roleid,
      roleName,
      parentId: parentRoleid
    }
    if (child && child.length > 0) {
      const r = formatTreeRoleList(child)
      temp.children = r
    }
    res.push(temp)
  })
  return res
}

const state = {
  token: '',
  agentId: '', // 代理id
  userName: '', // 用户名
  email: '', // 邮箱
  userId: '', // 用户ID
  roleId: '', // 当前登录用户的角色ID
  roles: [],
  permissions: [], // 后端返回的原始权限列表数据
  permissionTree: [], // 树形结构的权限数据
  userPermissionTree: [], // 当前用户的树形结构权限，直接在tree组件使用
  allocationRoleList: [], // 后端返回的原始可分配的角色列表
  allocationRoleTree: [], // 经过处理后的树形数据结构可分配的角色列表
  apiPermission: [] // api 的权限数组
}

const mutations = {
  SET_TOKEN: (state, token) => {
    state.token = token
  },
  SET_USER_NAME: (state, userName) => {
    state.userName = userName
  },
  SET_EMAIL: (state, email) => {
    state.email = email
  },
  SET_USER_ID: (state, userId) => {
    state.userId = userId
  },
  SET_ROLE_ID: (state, roleId) => {
    state.roleId = roleId
  },
  SET_AGENT_ID: (state, agentId) => {
    state.agentId = agentId
  },
  SET_ROLES: (state, roles) => {
    state.roles = roles
  },
  /**
   * 存储后端返回的原始权限列表数据
   * @param {Object} state state
   * @param {array} permissions 后端返回的原始权限列表数据
   * @returns {void}
   */
  SET_PERMISSIONS: (state, permissions) => {
    state.permissions = permissions
  },
  /**
   * 存储树形结构的权限数据
   * @param {Object} state state
   * @param {array} permissionTree 树形结构的权限数据
   * @returns {void}
   */
  SET_PERMISSION_TREE: (state, permissionTree) => {
    state.permissionTree = permissionTree
  },
  /**
   * 存储当前登录用户的权限树形结构数据
   * @param {Object} state state
   * @param {array} userPermissionTree 当前登录用户的权限树形结构数据
   * @returns {void}
   */
  SET_USER_PERMISSION_TREE: (state, userPermissionTree) => {
    state.userPermissionTree = userPermissionTree
  },
  /**
   * 存储后端返回的原始可分配的角色列表数据
   * @param {Object} state state
   * @param {array} allocationRoleList 原始可分配的角色列表数据
   * @returns {void}
   */
  SET_ALLOCATION_ROLE_LIST: (state, allocationRoleList) => {
    state.allocationRoleList = allocationRoleList
  },
  /**
   * 存储经过处理后的树形数据结构可分配的角色列表
   * @param {Object} state state
   * @param {array} allocationRoleTree 处理后的树形数据结构可分配的角色列表
   * @returns {void}
   */
  SET_ALLOCATION_ROLE_TREE: (state, allocationRoleTree) => {
    state.allocationRoleTree = allocationRoleTree
  },
  /**
   * 存储api的权限数据
   * @param {Object} state state
   * @param {array} apiPermission api的权限数据
   * @returns {void}
   */
  SET_API_PERMISSION: (state, apiPermission) => {
    state.apiPermission = apiPermission
  }
}

const actions = {
  /**
   * 设置token
   * @param {Function} commit commit
   * @returns {void}
   */
  setToken({ commit }) {
    commit('SET_TOKEN', getToken())
  },

  /**
   * 用户登录
   * @param {Function} commit commit
   * @param {{ passport: string, password: string }} param 入参
   * @param {string} param.passport 账号
   * @param {string} param.password 密码
   * @returns {Promise} Promise
   */
  login({ commit }, { passport, password }) {
    return new Promise((resolve, reject) => {
      apiLogin({ passport, password }).then(({ data: { token }}) => {
        commit('SET_TOKEN', token)
        setToken(token)
        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },

  /**
   * 临时token登录
   * @param {Function} commit commit
   * @param {string} accountToken 临时token
   * @returns {Promise} Promise实例
   */
  accountTokenLogin({ commit }, { accountToken }) {
    return new Promise((resolve, reject) => {
      apiAccountTokenLogin({ accountToken }).then(({ data: { token }}) => {
        commit('SET_TOKEN', token)
        setToken(token)
        resolve()
      }).catch(e => {
        reject(e)
      })
    })
  },

  /**
   * 获取用户的信息
   * @param {Function} commit commit
   * @returns {Promise} Promise实例
   */
  async getUserInfo({ commit }) {
    try {
      const { data: { email, name: userName, agentid: agentId, userid: userId, roleid, account }} = await apiGetUserInfo()
      commit('SET_USER_NAME', userName)
      commit('SET_EMAIL', email)
      commit('SET_USER_ID', userId)
      commit('SET_ROLE_ID', roleid)
      commit('SET_AGENT_ID', agentId)
      return { userName, email, userId, roleid, account }
    } catch (e) {
      throw new Error(e.msg || e.message)
    }
  },

  /**
   * 获取当前登录用户的权限列表信息
   * @param {Function} commit commit
   * @returns {Promise} Promise实例
   */
  getUserPermission({ commit, state }) {
    return new Promise((resolve, reject) => {
      apiGetUserPermission().then(({ data }) => {
        // 区分目录、页面、按钮权限为一个数组，接口权限为另外一个数组
        const { nodes: apiPermission } = data
        let { menus: planPermission } = data

        // 区分是否为内部账号，区分依据在于roleid是否为-1或0
        // -1： 后台超级管理员特权账号
        // 0：内部普通账号
        // 如果是内部账号，需要进行路由屏蔽处理
        const roleId = state.roleId
        if (roleId === 0) {
          planPermission = filterWhiteRouter(planPermission)
        }

        // 获取按钮级别权限
        const roles = generateRoles(planPermission)

        // 不具备任何按钮级权限时，伪造一个空的按钮权限，解决空按钮权限下无限死循环的问题
        if (!roles.length) {
          roles.push('')
        }

        const permissionTree = generatePermissionTree(deepClone(planPermission).reverse())
        // console.log(permissionTree)

        commit('SET_PERMISSIONS', data)
        commit('SET_PERMISSION_TREE', permissionTree)
        commit('SET_ROLES', roles)
        commit('SET_USER_PERMISSION_TREE', generateTreeData(permissionTree))
        commit('SET_API_PERMISSION', apiPermission)
        resolve({ permissionTree, apiPermission })
      })
    })
  },

  /**
   * 获取当前登录用户可分配的角色列表
   * @param {Function} commit commit
   * @returns {Promise} Promise实例
   */
  getAllocationRole({ commit, state }) {
    return new Promise((resolve, reject) => {
      apiGetOperableRoleList().then(({ data }) => {
        const [children] = data
        const { child } = children
        const list = transformRoleList(deepClone(child))
        const treeData = formatTreeRoleList(child)
        // const treeData = generateCascaderRole(deepClone(data), state.roleId)
        commit('SET_ALLOCATION_ROLE_LIST', list)
        commit('SET_ALLOCATION_ROLE_TREE', treeData)
        resolve(treeData)
      }).catch(e => {
        reject(e)
      })
    })
  },

  logOut() {
    const ssoFlag = sessionStorage.getItem('sso') === '1'
    // 重置标记符
    ssoFlag && sessionStorage.removeItem('sso')
    removeToken()

    // 判断当前登录用户是从统一登录入口过来的还是子系统的登录入口进入的
    // 两个判断条件，一个是当前选项卡中缓存的sso标记符，另外一个是token的键值是否为默认键值
    // 统一登录入口进入的，需要跳转回统一登录入口
    // 从子系统的登录入口进入的，回到子系统的登录入口
    if (ssoFlag) {
      // 获取当前的域名地址
      const currentDomain = `${currentOrigin.protocol}//${currentOrigin.host}`
      let url = ''
      if (process.env.NODE_ENV === 'development') {
        url = `${currentDomain}/sso`
      } else {
        console.log('统一平台的登陆网址：', process.env.VUE_APP_SSO)
        url = `${process.env.VUE_APP_SSO}`
      }
      sessionStorage.setItem('redirect', url)
      window.location.href = url
    } else {
      window.location.reload()
    }
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
